#include <iostream>
#include <string>
#include <string.h>
#include <errno.h>
#include <poll.h>

#include "Sock.hpp"
#include "log.hpp"
#include "err.hpp"

const static uint16_t defaultport = 8888; // 默认端口号
const static int N = 4096;                // 默认事件管理集大小
const static int defaultfd = -1;          // 默认文件描述符
const static short defaultevent = 0;      // 默认关心事件
typedef pollfd type_t;

class PollServer
{
public:
    PollServer(uint16_t port = defaultport) : _port(port)
    {
    }

    void InitServer()
    {
        _listensock.Socket();
        _listensock.Bind(_port);
        _listensock.Listen();
        _fdarray = new type_t[N];
        // 初始化事件管理集
        for (int i = 0; i < N; ++i)
        {
            _fdarray[i].fd = defaultfd;
            _fdarray[i].events = defaultevent;
            _fdarray[i].revents = defaultevent;
        }
    }
    // 连接获取
    void Accept()
    {
        std::string clientIp;
        uint16_t clientPort;
        int sock = _listensock.Accept(&clientIp, &clientPort);
        std::string name = "[" + clientIp + ":" + std::to_string(clientPort) + "]";
        if (sock < 0)
            return;

        int i = 1;
        for (; i < N; ++i)
        {
            if (_fdarray[i].fd != defaultfd)
                continue;
            _fdarray[i].fd = sock;
            _fdarray[i].events = POLLIN; // 关心读事件
            _fdarray[i].revents = defaultevent;
            logMessage(Info, "%s连接到来,sock:%d", name.c_str(), sock);
            break;
        }
        // 连接管理已打上限
        if (i >= N)
        {
            std::string echo = "当前连接已满,请稍后尝试";
            send(sock, echo.c_str(), echo.size(), 0);
            close(sock);
        }
    }

    void Recv(int indix)
    {
        int fd = _fdarray[indix].fd;
        char buffer[1024];
        int n = recv(fd, buffer, sizeof(buffer) - 1, 0);
        if (n < 0)
            logMessage(Warning, "recv error,%d:%s", errno, strerror(errno));
        else if (n > 0)
        {
            buffer[n] = '\0';
            std::cout << "client# " << buffer << std::endl;
            // 返回响应
            std::string echo = "[server echo] ";
            echo += buffer;
            send(fd, echo.c_str(), echo.size(), 0);
        }
        else
        {
            // 客户端关闭连接
            logMessage(Info, "client quit...%d", fd);
            close(fd);
            _fdarray[indix].fd = defaultfd;
        }
    }

    void HandlerEvent()
    {
        for (int i = 0; i < N; ++i)
        {
            int fd = _fdarray[i].fd;
            short revent = _fdarray[i].revents;
            if (fd == defaultfd)
                continue;
            
            if (fd == _listensock.Fd() && (revent & POLLIN))
                Accept();// 连接事件到来
            else if (fd != _listensock.Fd() && (revent & POLLIN))
                Recv(i);// 读事件到来
        }
    }

    void Start()
    {
        _fdarray[0].fd = _listensock.Fd();
        _fdarray[0].events = POLLIN; // 连接到来是读事件
        while (true)
        {
            int timeout = -1;
            // timeout小于0，代表阻塞式等待
            int n = poll(_fdarray, N, timeout);
            switch (n)
            {
            case 0://超时
                logMessage(Info, "timeout...%d:%s", errno, strerror(errno));
                break;
            case -1://出错
                logMessage(Warning, "select error,&d:%s", errno, strerror(errno));
                break;
            default:
                // 有事件就绪
                HandlerEvent();
                continue;
            }
        }
    }

    ~PollServer()
    {
    }

private:
    uint16_t _port;   // 端口号
    Sock _listensock; // 监听套接字
    type_t *_fdarray;
};